Skip to content

ci: 合并时收口另一个仓库里被 Fixes 声明的 issue(缺凭据时改为出声,不静默) - #4553

Merged
os-zhuang merged 2 commits into
mainfrom
claude/cross-repo-fixes-closer
Aug 2, 2026
Merged

ci: 合并时收口另一个仓库里被 Fixes 声明的 issue(缺凭据时改为出声,不静默)#4553
os-zhuang merged 2 commits into
mainfrom
claude/cross-repo-fixes-closer

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

GitHub 的关闭关键字只在同仓库内生效。本仓库一个写着 Fixes objectstack-ai/objectui#456 的 PR,在人眼里和同仓库关闭长得完全一样,合并后那个 issue 却会永远开着——而且目标 issue 页面上也不会出现这条 PR 的任何引用,下一个读者无从找到修复在哪。

v17 验收批次(#4482)撞了两次:#4475#4478 的修复都落在 objectui,两个 framework 侧 issue 都是人工关掉的。这次是把那两次手工动作固化下来。

两种模式,都可见

有 CROSS_REPO_ISSUE_TOKEN  → 关闭目标 issue,并在其上留下指向本 PR 的说明
无该 token                 → 在本 PR 上留言,点名哪些 issue 仍需手工关闭

第二种模式是刻意设计的,不是降级凑合。

本仓库现有的 secret 只有 GITHUB_TOKENNPM_TOKEN,而 GITHUB_TOKEN 的写权限被限制在运行工作流的那个仓库内——它关不掉另一个仓库的 issue,这正是本问题的成因。所以在管理员配置跨仓库凭据之前,这个工作流没有能力完成关闭动作。

那种情况下它必须出声。一个因为 secret 从未配置而悄悄什么都不做的工作流,正是这个仓库反复在修的形状——#4449validateFormLayout 写了、测了、导出了,却没有任何命令调用它,"它存在多久,就在零个 stack 上跑了多久"。缺失的凭据必须自己announce,而不是让人以为已经接好了。

需要管理员做的事(本 PR 无法自带)

新增仓库 secret CROSS_REPO_ISSUE_TOKEN:对目标仓库具备 issues: write 的 fine-grained PAT 或 GitHub App token。组织里已安装的 GitHub App 即可胜任,不必用个人 PAT。

配置前后行为都正确,只是能力不同;配置后本 PR 的提示评论会自动不再出现。

实现要点

  • 只匹配限定形式 owner/repo#N。裸 #N 由 GitHub 原生处理,绝不触碰。已自测:Fixes #4441 不命中,Fixes objectstack-ai/objectui#3134 命中。
  • 同仓库的限定写法会被过滤掉thisRepo 比较),否则每次合并都会在已被 GitHub 关闭的 issue 上多留一条无意义评论。
  • 已经 closed 的目标跳过,不重复关闭、不重复评论。
  • 单个目标失败不吞掉其余目标,且失败走 core.warning 而非静默——一次失败不能读起来像成功。
  • pull_request_target 而非 pull_request,因为后者对来自 fork 的运行不下发 secret。pull_request_target 通常的风险(用写权限运行不受信任的 PR 代码)在这里不成立:本 job 从不 checkout head ref,也从不执行 PR 里的任何东西,只读 PR 正文并调用 issues API。

验证

  • YAML 解析通过;内嵌脚本按 actions/github-script 的 async 包装做 node --check,语法通过。
  • 正则以四条真实样本自测:三条跨仓库引用全部命中,裸 Fixes #4441 不命中。
  • 未做:端到端触发一次真实合并来验证。该工作流只在 pull_request_target: closedmerged == true 时运行,本 PR 自身合并即是它的第一次真实执行——届时它应当因缺少 token 而在本 PR 上留下那条提示评论,这本身就是可观察的验收信号

配套的同名工作流已在 objectui 侧一并提交(方向相反:那边的 PR 修本仓库的 issue)。


Generated by Claude Code

GitHub's closing keywords only act within a repository, so a PR here saying
`Fixes objectstack-ai/objectui#456` merges and leaves that issue open — with
no reference to the PR on the issue either. v17 verification hit this twice
(#4475, #4478); both were closed by hand.

The job has two modes and both are visible: with a cross-repo token it closes
the foreign issue and links the PR; without one it comments on the merged PR
naming what still needs closing. Silent no-op on a missing secret is the shape
this repo keeps having to fix (#4449), so the absent credential announces
itself instead.
@vercel

vercel Bot commented Aug 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 2, 2026 2:43am

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tooling labels Aug 2, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review August 2, 2026 07:41
@os-zhuang
os-zhuang added this pull request to the merge queue Aug 2, 2026

Copy link
Copy Markdown
Contributor Author

更正:正文「验证」一节里有一句声明站不住

原文写的是:

本 PR 自身合并即是它的第一次真实执行——届时它应当因缺少 token 而在本 PR 上留下那条提示评论,这本身就是可观察的验收信号

这句很可能不成立,不应作为验收依据。

pull_request_target 的工作流定义从 base 分支读取。本 PR 合并之前,main 上并不存在这个文件,所以它多半不会在自己的合并事件上运行。真正的首次执行,会是此后第一个正文带跨仓库关闭关键字的已合并 PR

更正后的验证状态如实列一遍:

状态
YAML 解析 ✅ 已验证
内嵌脚本语法(按 actions/github-script 的 async 包装 node --check ✅ 已验证
关键字正则(四条样本:三条跨仓库命中,裸 Fixes #4441 不命中) ✅ 已验证
端到端触发一次真实合并 未实测

也就是说:这个工作流的运行时行为一次都没有被真正执行过。 静态检查只能保证它不会因语法错误而崩,保证不了它在真实事件下做对事。

合并后建议主动确认一次:下一个带跨仓库 Fixes 的 PR 合并时,去 Actions 里看 Cross-repo Issue Closer 是否触发、以及它是否按预期在缺 token 时留下提示评论。若始终不触发,第一嫌疑是 pull_request_target 的事件/权限配置,而不是脚本逻辑。

(本条更正由协调会话在合并前补记——正文里那句话是我写的,属于「声称验证过、实际没有」的那一类,而这恰恰是本批次 #4482 反复在修的问题。留一条更正比让它随合并固化便宜得多。)


Generated by Claude Code

Merged via the queue into main with commit dab35e0 Aug 2, 2026
17 checks passed
@os-zhuang
os-zhuang deleted the claude/cross-repo-fixes-closer branch August 2, 2026 07:56
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Aug 3, 2026
…引入的红检查) (objectstack-ai#4573)

* fix(ci): rename the cross-repo client — github-script already declares `octokit`

`actions/github-script` injects an `octokit` binding, so `const octokit = ...`
aborts the run with a SyntaxError before any logic executes. Caught on objectstack-ai#4553's
own merge, the first time the workflow ever ran; until this lands every merged
PR carries one red check.

The pre-merge `node --check` missed it because the test wrapper declared only
{github, context, core, require} — a wrapper that omits an injected identifier
cannot see a collision with it. The wrapper now carries the full set.

* ci: log CROSS_REPO_ISSUE_TOKEN presence on every run

Without this the job returns early whenever a PR body carries no cross-repo
reference — which is most PRs — so a repository that has the secret and one
that does not produce byte-identical logs. Whether the credential is
provisioned stays unanswerable until a cross-repo reference happens to show
up, possibly days later.

Presence only; the value is never read into the log.

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd documentation Improvements or additions to documentation size/m tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants